#pragma once

#include <memory>
#include <list>

#include <uv.h>

#include "uvo_looped.h"

namespace anb { namespace net {

class write;

class connection_base : public uvo_looped {
public:
    connection_base(loop::ptr loop, uv_tcp_t* tcp, size_t headsize = LEN_SIZE);
	virtual ~connection_base();

	typedef boost::shared_ptr<connection_base> ptr;

    static const size_t LEN_SIZE = 4;

	const std::string& get_peername() const;

    uv_tcp_t* get_tcp() const;

    int start();
    virtual void stop();

	class listener {
	public:
		virtual ~listener();

		virtual void connection_stopped(connection_base* connection) = 0;
	};

	void add_listener(const std::weak_ptr<listener>& listener);

	void send(const uv_buf_t* segments, size_t count); // ???
	void send(write* write);

protected:
	void init_buffer(size_t headsize);

    static void _alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
    static void _read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
    static void _written(uv_write_t* req, int status);

    void alloc(size_t suggested_size, uv_buf_t* buf);
    void read(ssize_t nread);
    //void closed();

	virtual void handle_head(const uv_buf_t& segment);
	virtual void handle_body(const uv_buf_t& segment);

private:
    uv_tcp_t* m_tcp;
	std::string m_peername;

    uv_buf_t m_head;
    uv_buf_t m_body;
	// current reading buffer
    uv_buf_t* m_buf;
	size_t m_read;

	typedef std::weak_ptr<listener> listener_ptr;
	typedef std::list<listener_ptr> listeners;
	listeners m_listeners;
};


} }